package beer.coder.walawala.gui.util;

import beer.coder.walawala.common.config.ApplicationConfigure;
import beer.coder.walawala.common.constant.Constant;
import java.awt.SystemTray;
import java.net.URISyntaxException;
import java.util.function.Consumer;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

/**
 * 窗口初始化.
 *
 * @author amath0312
 * @version 1.0
 * @date 2019-10-07 19:29
 */
public class StageUtil {

  /**
   * 初始化walawala主窗口
   */
  public static Stage init(Stage stage, ApplicationConfigure configure, Consumer<ApplicationConfigure> save) {
    if (stage == null) {
      stage = new Stage();
    }
    stage.setTitle(Constant.APPNAME);
    stage.initStyle(StageStyle.UNDECORATED);
    stage.setResizable(true);
    stage.setAlwaysOnTop(true);

    stage.getIcons()
        .add(new Image(Thread.currentThread().getContextClassLoader().getResource("icon.png").toExternalForm()));

    stage
        .iconifiedProperty()
        .addListener(
            (observable, oldValue, newValue) ->
            {
              if (newValue) {
                System.out.println("最小化");
              } else {
                System.out.println("还原");
              }
            });
    stage.widthProperty().
        addListener((observable, oldValue, newValue) ->
        {
          configure.setWidth(newValue.intValue());
          if (save != null) {
            save.accept(configure);
          }
        });
    stage.heightProperty().
        addListener((observable, oldValue, newValue) ->
        {
          configure.setHeight(newValue.intValue());
          if (save != null) {
            save.accept(configure);
          }
        });

    stage.xProperty().addListener((observable, oldValue, newValue) ->
    {
      configure.setStartx(newValue.intValue());
      if (save != null) {
        save.accept(configure);
      }
    });

    stage.yProperty().addListener((observable, oldValue, newValue) ->
    {
      configure.setStarty(newValue.intValue());
      if (save != null) {
        save.accept(configure);
      }
    });
    stage.setWidth(configure.getWidth());
    stage.setHeight(configure.getHeight());

    stage.setX(configure.getStartx());
    stage.setY(configure.getStarty());

    return moveable(stage);
  }

  /**
   * 可在Stage的任意位置拖拽移动窗口.
   */
  public static Stage moveable(Stage stage) {
    stage.addEventHandler(
        MouseEvent.ANY,
        new EventHandler<MouseEvent>() {
          boolean isDragging = false;
          double sourceX;
          double sourceY;

          @Override
          public void handle(MouseEvent event) {
            if (event.getEventType() == MouseEvent.MOUSE_PRESSED
                && event.getButton() == MouseButton.PRIMARY) {
              isDragging = true;
              sourceX = event.getScreenX();
              sourceY = event.getScreenY();
            } else if (event.getEventType() == MouseEvent.MOUSE_DRAGGED) {
              if (isDragging) {
                double dx = event.getScreenX() - sourceX;
                double dy = event.getScreenY() - sourceY;
                stage.setX(stage.getX() + dx);
                stage.setY(stage.getY() + dy);
                sourceX = event.getScreenX();
                sourceY = event.getScreenY();
              }
            } else if (event.getEventType() == MouseEvent.MOUSE_RELEASED) {
              isDragging = false;
              sourceX = -1;
              sourceY = -1;
            }
          }
        });
    return stage;
  }

  public static void showStage(Stage stage) {
    Platform.runLater(() -> {
      if (stage.isIconified()) {
        stage.setIconified(false);
      }
      if (!stage.isShowing()) {
        stage.show();
      }

      stage.requestFocus();
      stage.toFront();
    });
  }

  public static void hideStage(Stage stage) {
    Platform.runLater(() -> {
      if (SystemTray.isSupported()) {
        stage.hide();
      } else {
        System.exit(0);
      }
    });
  }

  public static void switchStageStatus(Stage stage) {
    if (stage.isIconified() || !stage.isShowing()) {
      StageUtil.showStage(stage);
    } else {
      StageUtil.hideStage(stage);
    }
  }

  public static void exitStage(Stage stage, Consumer<Stage> onExit) {
    Platform.runLater(() -> {
      StageUtil.hideStage(stage);
      if (onExit != null) {
        onExit.accept(stage);
      }
      System.exit(0);
    });
  }
}
